从 DAS 开始了解 CKB 应用开发(一)—— 如何保证 DAS 账户的唯一性
近日,DAS 创始人 TimYang (杨敏)在 Nervos CKB 上开发了 DAS 去中心化账户服务。借着这次的产品开发,TimYang 将通过《从 DAS 开始了解 CKB 应用开发》系列文章,向大家阐述他的设计思路和开发历程,让大家了解如何在世界上第一个基于 UTXO 架构的公链 CKB 上构建产品级应用。
在第一篇文章中,Tim 将向大家介绍他们在设计 DAS 时面临的第一个大问题 —— 如何保证 DAS 账户的唯一性。欢迎阅读及体验。
开篇
DAS(Decentralized Account Services),是基于 CKB 构建的去中心化账户服务。DAS 项目本身,旨在为新世界提供一套兼具抗审查性、唯一性、可识别性的账户体系。在 DAS 的第一阶段,它看起来像是以太坊的 ENS,并且具备一些比 ENS 更为优秀的特性。但 DAS 要做的,不仅仅是更好的 ENS,而是试图为加密世界的「去中心化账户/身份」这块拼图,带来新的定义。
DAS 不是一个概念性产品,它目前已经运行在 CKB 测试网上,并预计于近期上线主网。可以通过 https://da.services 体验测试版本。
DAS 是基于 CKB 开发的区块链应用。在诸多公链中,为什么我们要选择基于 CKB 来进行开发呢?原因有二:
PoW 共识 + Cell(UTXO)模型 自定义密码学原语(高度开放的架构),基于此我们能够实现 DAS 账户可以被任意公链地址所持有。
在面对一个问题时,我们采用的思路和解决方案,不一定是最优解,甚至大概率不是。但这些满足我们场景的思路和解决方案,若能给大家带来启发,目的便已达到。 这一系列的文章,都假定读者已经充分理解 Cell 模型和「链下计算,链上验证」模型。
如何保证 DAS 账户的唯一性
每个 DAS 账户都需要一个 Cell 来存储其数据,Cell 是通过不同交易来创建的,这意味着 DAS 系统的全局状态数据是分散存储在各个角落的。同时每个 DAS 账户又必须具有唯一性。那么,当一个 DAS 账户注册行为发生时,我们如何判断该账户是否已经存在呢? 我们把这个问题一般化:对于分散存储的数据集,在插入数据时,如何保证每条数据的唯一性?
去中心化程度,对于 DAS 要达成的目标而言,去中心化是最基础性的原则 用户体验,技术方案不允许带来糟糕的用户体验 工程复杂度,越简单的架构往往越有效 费用成本低,能节省的费用尽量节省
方案一:把所有账户存储在一个 Cell 里
Cell 竞争问题,每个新账户的注册都需要把这个 GlobalStatusCell 作为输入花费掉,而一个 Live Cell 只能花费一次,那意味着同一时刻,永远只能处理一个注册请求。竞争 Cell 失败的用户,不得不一遍又一遍的签署交易,直到成功的竞争到 Cell。 空间成本问题,CKB 是分层架构,Layer 1 上最终的状态空间限制为大约 80 GB,在上面存储数据需要使用 CKB 购买存储空间。假设最终有 100w 个 DAS 账户被注册,那这个 GlobalStatusCell 需要的 capacity 将会巨大无比。当然,由于这个存储空间是随着注册量逐渐增加的,对于单个用户而言,只需为本次注册所对应的增量空间支付 CKB,单个用户的成本还算可以接受。
方案二:那就把所有账户分散到多个 Cell 里
依然存在一定的 Cell 竞争,如果按 hash 前3位来创建 SubStatusCell,需要提前创建 4096 个 SubStatusCell,假定在一个周期内有 50 个并发的注册请求,按照「抽屉原理」,仍有 26% 的概率出现 Cell 竞争。尽管 50 的并发请求稍显苛刻,在早期可能根本达不到,但应该认识到: 由于 SubStatusCell 数量固定,这种竞争的概率,无论在哪个阶段都是一样的 「概率」本身意味着不确定性,它的用户体验的影响可能没有,也可能非常大。 初始化时存在费用成本,假定一个 SubStatusCell 初始时只需要 100 CKB 作为其 capacity,那初始化所有的 SubStatusCell 就需要 409,600 个 CKB。
方案三:由 DAS 官方来判断一个账户是否已经注册过
不去中心化,如何确保 DAS 官方服务的唯一性判断是正确的。如果官方主动作恶呢?如果官方因为程序故障或者私钥保管不善,导致被动作恶呢? 脏数据问题,无论什么形式的作恶,中心化的判断都是一种链下判断,不能绝对有效的保证唯一性,因此,随时可能产生链上脏数据。如何清理这些脏数据呢?势必要引入一套脏数据清理的机制。 衍生而来的可用性问题,如果官方服务宕机,那整个注册服务就不可用。
方案四:那就多中心化,用多个链下节点一起判断一个账户是否已经注册过
信任问题,「可以信任」的组织,怎么样算可以信任的组织,我们应该如何甄选这 7 个节点。一个组织的道德或许是可以信任的,并不代表其行为也是可以信任的。我们可以找最有公信力的组织来做节点,但在一个项目的早期,最有公信力的组织很难有动力来维护节点。 脏数据问题,由于「必然」存在的程序 bug,这些超级节点们完全可能做出一致性的错误判断。当一致性的错误出现时,还得有一套脏数据清理逻辑机制 节点轮换问题,由于私钥丢失或者其他原因,节点不可避免的要进行轮换,轮换如何进行?通过链下商量还是链上共识?链下商量意味着得有一套公开透明的治理流程;链上共识,意味着要有的复杂的工程实现。 复杂度,这既包括工程的复杂度,也包括治理的复杂度。其中的大量工作都已经偏离了一个 dApp 本身的业务逻辑。试想,如果每个应用开发者都需要考虑这么多与业务逻辑关联度并不高的问题,那应用不可能被高效的创造出来。这也意味着,多中心的方案必然不能是最佳实践。
方案五:注册时不去重,解析时去重
开发者会都运行统一的解析程序吗? 当官方解析程序升级时,那些选择运行官方解析程序的开发者,他们会不会,以及能不能做到及时升级?
方案六:有序链表
对于分散存储的数据集,在插入数据时,如何保证每条数据的唯一性?
inputs 中,引入的父 AccountCell 的 account_id 是否小于新注册的账户的 account_id inputs 中,引入的父 AccountCell 的 next_account_id 是否大于新注册的账户的 account_id outputs 中,新的父 AccountCell 的 next_account_id 是否等于新注册账户的 account_id outputs 中,新注册账户的 next_account_id 是否等于 inputs 中引入的父 AccountCell 的 next_account_id
进一步衍生
判断个数据重复性而已,在 CKB 上就要这么复杂吗?
那为什么 CKB 要采用 UTXO 模型,ETH 的账户模型不就很好吗?
并行计算。ETH 的单个账户下的所有交易都必须串行,一笔交易卡住,后面所有的交易都无法进行。 用户数据存储在用户自己的 UTXO(Cell)里,而不是集中存储在合约中,不更符合去中心化精神吗?
应把链上验证看作一种协议
方案六也有 Cell 竞争问题呀?
在面对一个问题时,我们采用的思路和解决方案,不一定是最优解,甚至大概率不是。但这些满足我们场景的思路和解决方案,若能给大家带来启发,目的便已达到。
https://talk.nervos.org/